/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    clippy::never_loop
)]
use crate::common::*;
extern "C" {
    fn calloc(_: libc::c_ulong, _: libc::c_ulong) -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
    fn strdup(_: *const libc::c_char) -> *mut libc::c_char;
    fn strpbrk(_: *const libc::c_char, _: *const libc::c_char) -> *mut libc::c_char;
    fn strndup(_: *const libc::c_char, _: libc::c_ulong) -> *mut libc::c_char;
    fn __ctype_b_loc() -> *mut *const libc::c_ushort;
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_debug_exit_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
    );
    fn sudo_debug_register_v1(
        program: *const libc::c_char,
        subsystems: *const *const libc::c_char,
        ids: *mut libc::c_uint,
        debug_files: *mut sudo_conf_debug_file_list,
    ) -> libc::c_int;
    fn sudo_debug_set_active_instance_v1(inst: libc::c_int) -> libc::c_int;
    static mut sudoers_subsystem_ids: [libc::c_uint; 18];
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_debug_file {
    pub entries: C2RustUnnamed_0,
    pub debug_file: *mut libc::c_char,
    pub debug_flags: *mut libc::c_char,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct C2RustUnnamed_0 {
    pub tqe_next: *mut sudo_debug_file,
    pub tqe_prev: *mut *mut sudo_debug_file,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_conf_debug_file_list {
    pub tqh_first: *mut sudo_debug_file,
    pub tqh_last: *mut *mut sudo_debug_file,
}
static mut sudoers_debug_instance: libc::c_int = -(1 as libc::c_int);
static mut sudoers_subsystem_names: [*const libc::c_char; 19] = [
    b"alias\0" as *const u8 as *const libc::c_char,
    b"audit\0" as *const u8 as *const libc::c_char,
    b"auth\0" as *const u8 as *const libc::c_char,
    b"defaults\0" as *const u8 as *const libc::c_char,
    b"env\0" as *const u8 as *const libc::c_char,
    b"event\0" as *const u8 as *const libc::c_char,
    b"ldap\0" as *const u8 as *const libc::c_char,
    b"logging\0" as *const u8 as *const libc::c_char,
    b"main\0" as *const u8 as *const libc::c_char,
    b"match\0" as *const u8 as *const libc::c_char,
    b"netif\0" as *const u8 as *const libc::c_char,
    b"nss\0" as *const u8 as *const libc::c_char,
    b"parser\0" as *const u8 as *const libc::c_char,
    b"perms\0" as *const u8 as *const libc::c_char,
    b"plugin\0" as *const u8 as *const libc::c_char,
    b"rbtree\0" as *const u8 as *const libc::c_char,
    b"sssd\0" as *const u8 as *const libc::c_char,
    b"util\0" as *const u8 as *const libc::c_char,
    0 as *const libc::c_char,
];

/*
 * Parse the "filename flags,..." debug_flags entry and insert a new
 * sudo_debug_file struct into debug_files.
 */
#[no_mangle]
pub unsafe extern "C" fn sudoers_debug_parse_flags(
    mut debug_files: *mut sudo_conf_debug_file_list,
    mut entry: *const libc::c_char,
) -> bool {
    let mut debug_file: *mut sudo_debug_file = std::ptr::null_mut::<sudo_debug_file>();
    let mut filename: *const libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut flags: *const libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut namelen: size_t = 0;

    /* Already initialized? */
    if sudoers_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER {
        return true;
    }

    /* Only process new-style debug flags: filename flags,... */
    filename = entry;
    if *filename as libc::c_int != '/' as i32 || {
        flags = strpbrk(filename, b" \t\0" as *const u8 as *const libc::c_char);
        flags.is_null()
    } {
        return true;
    }
    namelen = flags.offset_from(filename) as libc::c_long as size_t;
    while isblank!(*flags) != 0 {
        flags = flags.offset(1);
    }

    'oom: loop {
        if *flags as libc::c_int != '\0' as i32 {
            debug_file = calloc(
                1 as libc::c_int as libc::c_ulong,
                ::core::mem::size_of::<sudo_debug_file>() as libc::c_ulong,
            ) as *mut sudo_debug_file;
            if debug_file.is_null() {
                break 'oom;
            }
            (*debug_file).debug_file = strndup(filename, namelen);
            if ((*debug_file).debug_file).is_null() {
                break 'oom;
            }
            (*debug_file).debug_flags = strdup(flags);
            if ((*debug_file).debug_flags).is_null() {
                break 'oom;
            }
            (*debug_file).entries.tqe_next = std::ptr::null_mut::<sudo_debug_file>();
            (*debug_file).entries.tqe_prev = (*debug_files).tqh_last;
            *(*debug_files).tqh_last = debug_file;
            (*debug_files).tqh_last = &mut (*debug_file).entries.tqe_next;
        }
        return true;
    } // 'oom loop

    if !debug_file.is_null() {
        free((*debug_file).debug_file as *mut libc::c_void);
        free((*debug_file).debug_flags as *mut libc::c_void);
        free(debug_file as *mut libc::c_void);
    }
    sudo_warnx_nodebug_v1(
        b"%s: %s" as *const u8 as *const libc::c_char,
        b"sudoers_debug_parse_flags\0" as *const u8 as *const libc::c_char,
        b"unable to allocate memory\0" as *const u8 as *const libc::c_char,
    );
    false
}

/*
 * Register the specified debug files and program with the
 * debug subsystem, freeing the debug list when done.
 * Sets the active debug instance as a side effect.
 */
#[no_mangle]
pub fn sudoers_debug_register(
    mut program: *const libc::c_char,
    mut debug_files: *mut sudo_conf_debug_file_list,
) -> bool {
    let mut debug_file: *mut sudo_debug_file = std::ptr::null_mut::<sudo_debug_file>();
    let mut debug_next: *mut sudo_debug_file = std::ptr::null_mut::<sudo_debug_file>();

    /* Already initialized? */
    unsafe {
        if sudoers_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER {
            sudo_debug_set_active_instance_v1(sudoers_debug_instance);
        }

        /* Setup debugging if indicated. */
        if !debug_files.is_null() && !((*debug_files).tqh_first).is_null() {
            if !program.is_null() {
                sudoers_debug_instance = sudo_debug_register_v1(
                    program,
                    sudoers_subsystem_names.as_ptr(),
                    sudoers_subsystem_ids.as_mut_ptr(),
                    debug_files,
                );
                if sudoers_debug_instance == SUDO_DEBUG_INSTANCE_ERROR {
                    return false;
                }
            }
            debug_file = (*debug_files).tqh_first;
            while !debug_file.is_null() && {
                debug_next = (*debug_file).entries.tqe_next;
                1 as libc::c_int != 0
            } {
                if !((*debug_file).entries.tqe_next).is_null() {
                    (*(*debug_file).entries.tqe_next).entries.tqe_prev =
                        (*debug_file).entries.tqe_prev;
                } else {
                    (*debug_files).tqh_last = (*debug_file).entries.tqe_prev;
                }
                *(*debug_file).entries.tqe_prev = (*debug_file).entries.tqe_next;
                free((*debug_file).debug_file as *mut libc::c_void);
                free((*debug_file).debug_flags as *mut libc::c_void);
                free(debug_file as *mut libc::c_void);
                debug_file = debug_next;
            }
        }
    }
    true
}

/*
 * Deregister sudoers_debug_instance if it is registered.
 */
#[no_mangle]
pub fn sudoers_debug_deregister() {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PLUGIN!());

        if sudoers_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER {
            sudo_debug_exit_v1(
                get_function_name!(),
                get_file_name!(),
                line!() as libc::c_int,
                sudo_debug_subsys as libc::c_int,
            );

            sudo_debug_deregister_v1(sudoers_debug_instance);
            sudoers_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
        }
    } //unsafe
}
